package com.jumi.microservice.service.logistics.admin;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.exception.ExcelCommonException;
import com.alibaba.fastjson.JSON;
import com.aliyuncs.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jumi.microservice.common.base.dto.ExportExcelCommonResponse;
import com.jumi.microservice.common.exception.BaseException;
import com.jumi.microservice.common.page.TableDataInfo;
import com.jumi.microservice.dto.logistics.*;
import com.jumi.microservice.dto.logistics.excel.ExcelSpiltMerge;
import com.jumi.microservice.entity.LogisticsGoods;
import com.jumi.microservice.entity.OrderLogistics;
import com.jumi.microservice.enumerate.*;
import com.jumi.microservice.mapper.LogisticsGoodsMapper;
import com.jumi.microservice.mapper.OrderLogisticsMapper;
import com.jumi.microservice.material.dto.category.JmCategoryResponse;
import com.jumi.microservice.material.dto.warehouse.JmWarehouseResponse;
import com.jumi.microservice.material.service.IJmCategoryService;
import com.jumi.microservice.material.service.IJmWarehouseService;
import com.jumi.microservice.service.logistics.AutoSpiltService;
import com.jumi.microservice.service.logistics.excel.SpiltMergeListener;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author by mazhao
 * @Classname MergeListService
 * @Description TODO
 * @Date 2020/8/10 16:27
 */
@Service
public class MergeService {

    private static final Logger log = LoggerFactory.getLogger(MergeService.class);

    @Resource
    OrderLogisticsMapper orderLogisticsMapper;

    @Resource
    LogisticsGoodsMapper logisticsGoodsMapper;

    @Resource
    AutoSpiltService autoSpiltService;

    @Resource
    RelocateService relocateService;

    @DubboReference
    IJmCategoryService iSpiltMergeCategoryService;

    @DubboReference
    IJmWarehouseService iWarehouseService;

    @Resource
    MergeService mergeService;

    private static List<ExcelSpiltMerge> errorList = new ArrayList<>();

    /**
     * 合单列表页
     *
     * @param request
     * @return
     */
    public TableDataInfo<MergeListResponse> list(MergeListRequest request) {
        TableDataInfo tableDataInfo = new TableDataInfo();
        List<MergeListResponse> result = new ArrayList<>();
        Page<Map<String, Object>> page = new Page<>(request.getPageNum(), request.getPageSize());
        if (request.getOrderNoList() != null) {
            request.setOrderNoList(request.getOrderNoList().replace("，", ","));
        }
        IPage<Map<String, Object>> records = orderLogisticsMapper.getReceiverInfoByPackageCount(request.getBenchmarkTime(),
                request.getGoodsName(), request.getOrderNoList(), request.getReceiverName(),request.getReceiverPhone(),page);
        List<Map<String, Object>> receiverInfoList = records.getRecords();
        if (receiverInfoList.isEmpty()) {
            tableDataInfo.setTotal(0L);
            tableDataInfo.setRows(result);
            return tableDataInfo;
        }
        QueryWrapper<OrderLogistics> orderLogisticsQueryWrapper = new QueryWrapper<>();
        orderLogisticsQueryWrapper.eq("del_flag", 0)
                .eq("is_spilt_merge_confirm", IsSpiltMergeConfirmEnum.NO_CONFIRM.getCode())
                .ge("logistics_status", LogisticsStatusEnum.WAIT_SEND.getCode())
                .le("create_time", request.getBenchmarkTime())
                .eq("self_flag", SelfFlagEnum.YES_SELF.getCode())
                .in("receiver_info", receiverInfoList.stream().map(r -> r.get("receiverInfo").toString())
                        .collect(Collectors.toList()))
                .in("warehouse", receiverInfoList.stream().map(r -> Integer.parseInt(r.get("warehouse").toString()))
                        .collect(Collectors.toList()));
        //获取目前符合排名的未确认拆合单的所有包裹
        List<OrderLogistics> orderLogisticsList = orderLogisticsMapper.selectList(orderLogisticsQueryWrapper);
        if (orderLogisticsList.isEmpty()) {
            tableDataInfo.setTotal(0L);
            tableDataInfo.setRows(result);
            return tableDataInfo;
        }
        //获取这些包裹下的商品信息
        Map<String, List<LogisticsGoods>> goodsMap = getLogisticsGoods(orderLogisticsList);
        for (Map<String, Object> r : receiverInfoList) {
            List<PackageInfo> packageInfoList = new ArrayList<>();
            MergeListResponse mergeListResponse = new MergeListResponse();
            mergeListResponse.setReceiverAddress(r.get("receiverAddress").toString());
            mergeListResponse.setReceiverPhone(r.get("receiverPhone").toString());
            mergeListResponse.setReceiverName(r.get("receiverName").toString());
            mergeListResponse.setWarehouse(Integer.parseInt(r.get("warehouse").toString()));
            //获取这个收货人以及这个收货人下的仓库的包裹
            List<OrderLogistics> list = getLogisticsByReceiverAndWarehouse(r, orderLogisticsList);
            for (OrderLogistics p : list) {
                PackageInfo packageInfo = getPackageInfo(p, goodsMap);
                if (packageInfo.getOrderNoList().isEmpty()) {
                    continue;
                }
                packageInfoList.add(packageInfo);
            }
            mergeListResponse.setList(packageInfoList);
            mergeListResponse.setPackageAmount(packageInfoList.size());
            result.add(mergeListResponse);
        }
        result = result.stream().sorted(Comparator.comparing(MergeListResponse::getPackageAmount).reversed())
                .collect(Collectors.toList());
        tableDataInfo.setRows(result);
        tableDataInfo.setTotal(records.getTotal());
        return tableDataInfo;
    }

    /**
     * 根据收货人＆仓库获取符合条件包裹
     *
     * @param list
     * @param map
     * @return
     */
    public List<OrderLogistics> getLogisticsByReceiverAndWarehouse(Map<String, Object> map, List<OrderLogistics> list) {
        List<OrderLogistics> result = list.stream()
                .filter(p -> p.getWarehouse().equals(Integer.parseInt(map.get("warehouse").toString()))
                        && p.getReceiverInfo().equals(map.get("receiverInfo").toString()))
                .collect(Collectors.toList());
        return result;
    }

    /**
     * 生成包裹
     *
     * @param orderLogistics
     * @param goodsMap
     * @return
     */
    public PackageInfo getPackageInfo(OrderLogistics orderLogistics, Map<String, List<LogisticsGoods>> goodsMap) {
        PackageInfo packageInfo = new PackageInfo();
        BeanUtils.copyProperties(orderLogistics, packageInfo);
        List<GoodsEntity> list = new ArrayList<>();
        Set<String> set = new HashSet<>();
        int goodsAmount = 0;
        List<LogisticsGoods> logisticsGoodsList = new ArrayList<>();
        if (goodsMap.containsKey(orderLogistics.getLogisticsNo())) {
            logisticsGoodsList = goodsMap.get(orderLogistics.getLogisticsNo()).stream()
                    .sorted(Comparator.comparing(LogisticsGoods::getCreateTime).reversed()).collect(Collectors.toList());
        }
        for (LogisticsGoods g : logisticsGoodsList) {
            //获取物品信息
            GoodsEntity goodsEntity = new GoodsEntity();
            BeanUtils.copyProperties(g, goodsEntity);
            set.add(g.getOrderNo());
            goodsEntity.setGoodsAmount(g.getGoodsAmount());
            goodsAmount += g.getGoodsAmount();
            list.add(goodsEntity);
        }
        packageInfo.setList(list);
        packageInfo.setGoodsAmount(goodsAmount);
        packageInfo.setOrderNoList(set);
        packageInfo.setGoodsCount(list.size());
        packageInfo.setDescription("包含" + set.size() + "个订单，共" + goodsAmount + "件商品");
        return packageInfo;
    }

    /**
     * 编辑确定 包裹
     *
     * @param request
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean editConfirm(MergeSubmitRequest request) {
        List<PackageInfo> packageInfoList = request.getPackageList();
        List<String> logisticsNos = packageInfoList.stream().map(PackageInfo::getLogisticsNo).collect(Collectors.toList());
        //删除包裹商品
        UpdateWrapper<LogisticsGoods> delUpdateWrapper = new UpdateWrapper<>();
        delUpdateWrapper.eq("del_flag", 0).in("logistics_no", logisticsNos)
                .eq("logistics_status", LogisticsStatusEnum.WAIT_SEND.getCode()).eq("logistics_step", 1);
        LogisticsGoods delLogisticsGoods = new LogisticsGoods();
        delLogisticsGoods.setDelFlag((byte) 1);
        logisticsGoodsMapper.update(delLogisticsGoods, delUpdateWrapper);
        for (PackageInfo p : packageInfoList) {
            List<GoodsEntity> goodsEntityList = p.getList();
            //验证是否是新增包裹
            if (isNewLogistics(p.getLogisticsNo()) && !goodsEntityList.isEmpty()) {
                OrderLogistics orderLogistics = new OrderLogistics();
                BeanUtils.copyProperties(p, orderLogistics);
                orderLogistics.setReceiverInfo(p.getReceiverPhone() + p.getReceiverAddress());
                orderLogistics.setSpiltMergeStatus(SpiltMergeStatusEnum.SPILT.getCode());
                orderLogisticsMapper.insert(orderLogistics);
            }
            for (GoodsEntity g : goodsEntityList) {
                if (g.getIsRule().equals(IsRuleEnum.YES_RULE.getCode()) && g.getGoodsAmount() > g.getGoodsMaxAmount()) {
                    throw new BaseException(500, g.getGoodsName() + " 不符合所设拆单规则数量！");
                }
                QueryWrapper<LogisticsGoods> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("id", g.getId());
                LogisticsGoods logisticsGoods = logisticsGoodsMapper.selectOne(queryWrapper);
                LogisticsGoods newLogisticsGoods = new LogisticsGoods();
                BeanUtils.copyProperties(logisticsGoods, newLogisticsGoods);
                newLogisticsGoods.setLogisticsNo(g.getLogisticsNo());
                newLogisticsGoods.setGoodsAmount(g.getGoodsAmount());
                newLogisticsGoods.setId(null);
                newLogisticsGoods.setDelFlag((byte) 0);
                logisticsGoodsMapper.insert(newLogisticsGoods);
            }
        }
        for (String logisticsNo : logisticsNos) {
            if (!isHaveGoods(logisticsNo)) {
                UpdateWrapper<OrderLogistics> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("logistics_no", logisticsNo);
                orderLogisticsMapper.delete(updateWrapper);
            }
        }
        delUpdateWrapper = new UpdateWrapper<>();
        delUpdateWrapper.eq("del_flag", 1).in("logistics_no", logisticsNos)
                .eq("logistics_status", LogisticsStatusEnum.WAIT_SEND.getCode()).eq("logistics_step", 1);
        logisticsGoodsMapper.delete(delUpdateWrapper);
        return true;
    }

    /**
     * 是否是新增包裹
     *
     * @param logisticsNo
     * @return
     */
    public boolean isNewLogistics(String logisticsNo) {
        QueryWrapper<OrderLogistics> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("del_flag", 0).eq("logistics_no", logisticsNo);
        return orderLogisticsMapper.selectCount(queryWrapper) == 0;
    }


    /**
     * 是否还有商品
     *
     * @param logisticsNo
     * @return
     */
    public boolean isHaveGoods(String logisticsNo) {
        QueryWrapper<LogisticsGoods> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("del_flag", 0).eq("logistics_no", logisticsNo);
        return logisticsGoodsMapper.selectCount(queryWrapper) > 0;
    }

    /**
     * 获取该商品允许添加的包裹列表
     *
     * @param request
     * @return
     */
    public List<PackageInfo> getAllowAddGoodsPackageInfoList(MergeAllowAddRequest request) {
        List<PackageInfo> result = new ArrayList<>();
        Integer goodsLabel = request.getGoodsLabel();
        Integer goodsId = request.getGoodsId();
        Integer goodsAmount = request.getGoodsAmount();
        String logisticsNo = request.getLogisticsNo();
        List<PackageInfo> packageList = request.getPackageList();
        for (PackageInfo packageInfo : packageList) {
            if (packageInfo.getIsAlone() != null && packageInfo.getIsAlone().equals(IsAloneEnum.YES.getCode())) {
                continue;
            }
            List<GoodsEntity> list = packageInfo.getList();
            if (list == null || list.isEmpty()) {
                if(!result.contains(packageInfo)){
                    result.add(packageInfo);
                }
                continue;
            }
            List<Integer> goodsIdList = list.stream().map(GoodsEntity::getGoodsId).collect(Collectors.toList());
//            Map<Integer, Integer> ruleAmountMap = getRuleAmountMap(list);
            for (GoodsEntity goodsEntity : list) {
                if (goodsEntity.getGoodsLabel().equals(goodsLabel)) {
                    if ((!goodsIdList.contains(goodsId))) {
                        if(!result.contains(packageInfo)){
                            result.add(packageInfo);
                        }
                    }
                    if (goodsIdList.contains(goodsId)) {
                        if (goodsEntity.getGoodsId().equals(goodsId) && goodsEntity.getIsRule().equals(IsRuleEnum.YES_RULE.getCode())) {
                            if (goodsEntity.getGoodsMaxAmount() > 0 && goodsEntity.getGoodsMaxAmount() >= goodsEntity.getGoodsAmount() + goodsAmount) {
                                if(!result.contains(packageInfo)){
                                    result.add(packageInfo);
                                }
                            }
                        } else if (goodsEntity.getGoodsId().equals(goodsId) && goodsEntity.getIsRule().equals(IsRuleEnum.NO_RULE.getCode())) {
                            if(!result.contains(packageInfo)){
                                result.add(packageInfo);
                            }
                        }
                    }

                }
            }
        }
        return result.stream().filter(p -> !p.getLogisticsNo().equals(logisticsNo)).collect(Collectors.toList());
    }


    /**
     * 获取此商品规则数量
     *
     * @return
     */
//    public Map<Integer, Integer> getRuleAmountMap(List<GoodsEntity> goodsEntityList) {
//        List<Integer> spuIdList = goodsEntityList.stream().map(GoodsEntity::getSpuId).collect(Collectors.toList());
//        QueryWrapper<SpiltMergeSetup> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("del_flag", 0).eq("status", 1).in("spu_id", spuIdList);
//        List<SpiltMergeSetup> list = spiltMergeSetupMapper.selectList(queryWrapper);
//        Map<Integer, Integer> map = new HashMap<>(list.size());
//        for (SpiltMergeSetup spiltMergeSetup : list) {
//            map.put(spiltMergeSetup.getSpuId(), spiltMergeSetup.getSpiltMergeCount());
//        }
//        return map;
//    }


    /**
     * 确认拆合单结果
     *
     * @param request
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean spiltMergeSubmit(MergeSubmitRequest request) {
        List<PackageInfo> packageInfos = request.getPackageList();
        List<String> logisticsNoList = packageInfos.stream().map(PackageInfo::getLogisticsNo).collect(Collectors.toList());
        if (!logisticsNoList.isEmpty()) {
            orderLogisticsMapper.batchUpdateIsSpiltMergeConfirm(logisticsNoList,(byte)1);
            logisticsGoodsMapper.batchUpdateLogisticsStep(logisticsNoList);
        }
        return true;
    }

    /**
     * 批量确认拆合单结果
     *
     * @param request
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean allSpiltMergeSubmit(MergeRequest request) {
        QueryWrapper<OrderLogistics> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("del_flag", 0).eq("self_flag", SelfFlagEnum.YES_SELF.getCode())
                .eq("is_spilt_merge_confirm", IsSpiltMergeConfirmEnum.NO_CONFIRM.getCode())
                .le("create_time", request.getBenchmarkTime());
        boolean b = false;
        if(request.getReceiverName()!=null && !request.getReceiverName().isEmpty()){
            queryWrapper.eq("receiver_name",request.getReceiverName());
            b = true;
        }
        if(request.getReceiverPhone()!=null && !request.getReceiverPhone().isEmpty()){
            queryWrapper.eq("receiver_phone",request.getReceiverPhone());
            b = true;
        }
        QueryWrapper<LogisticsGoods> logisticsGoodsQueryWrapper = new QueryWrapper<>();
        logisticsGoodsQueryWrapper.eq("del_flag",0).eq("logistics_step",1)
                .eq("self_flag", SelfFlagEnum.YES_SELF.getCode())
                .eq("logistics_status",LogisticsStatusEnum.WAIT_SEND.getCode());
        if(request.getOrderNoList()!=null && !request.getOrderNoList().isEmpty()){
            logisticsGoodsQueryWrapper.in("order_no",request.getOrderNoList().split(","));
        }
        if(request.getGoodsName()!=null && !request.getGoodsName().isEmpty()){
            logisticsGoodsQueryWrapper.eq("goods_name",request.getGoodsName());
        }
        if(b){
            List<LogisticsGoods> list = logisticsGoodsMapper.selectList(logisticsGoodsQueryWrapper);
            if(!list.isEmpty()){
                List<String> logisticsNo = list.stream().map(LogisticsGoods::getLogisticsNo).collect(Collectors.toList());
                queryWrapper.in("logistics_no",logisticsNo);
            }
        }
        List<OrderLogistics> orderLogisticsList = orderLogisticsMapper.selectList(queryWrapper);
        if (orderLogisticsList.isEmpty()) {
            return false;
        }
        List<String> logisticsNoList = orderLogisticsList.stream().map(OrderLogistics::getLogisticsNo).collect(Collectors.toList());
        if (!logisticsNoList.isEmpty()) {
            orderLogisticsMapper.batchUpdateIsSpiltMergeConfirm(logisticsNoList,(byte)1);
            logisticsGoodsMapper.batchUpdateLogisticsStep(logisticsNoList);
        }
        return true;
    }

    /**
     * 自动合并包裹
     *
     * @param
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean autoMerge(MergeRequest request) {
        QueryWrapper<OrderLogistics> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("del_flag", 0).eq("is_alone", IsAloneEnum.NO.getCode())
                .eq("self_flag", SelfFlagEnum.YES_SELF.getCode())
                .eq("is_spilt_merge_confirm", IsSpiltMergeConfirmEnum.NO_CONFIRM.getCode())
                .ge("logistics_status", LogisticsStatusEnum.WAIT_SEND.getCode())
                .le("create_time", request.getBenchmarkTime()).orderByDesc("id");
        List<OrderLogistics> orderLogisticsList = orderLogisticsMapper.selectList(queryWrapper);
        if (orderLogisticsList.isEmpty()) {
            return true;
        }
        Map<String, List<LogisticsGoods>> goodsMap = getLogisticsGoods(orderLogisticsList);
        List<OrderLogistics> temp = new ArrayList<>(orderLogisticsList);
        List<LogisticsGoods> updateLogisticsGoodsNoList = new ArrayList<>();
        List<LogisticsGoods> updateLogisticsGoodsAmountList = new ArrayList<>();
        List<String> updateSpiltMergeStatusList = new ArrayList<>();
        List<Integer> updateLogisticsGoodsDelList = new ArrayList<>();
        orderLogisticsList = orderLogisticsList.stream().filter(o -> goodsMap.containsKey(o.getLogisticsNo())).collect(Collectors.toList());
        for (OrderLogistics orderLogistics : orderLogisticsList) {
            temp.remove(orderLogistics);
            for (OrderLogistics pp : temp) {
                List<LogisticsGoods> ll1 = new ArrayList<>();
                if (goodsMap.containsKey(orderLogistics.getLogisticsNo())) {
                    ll1 = new ArrayList<>(goodsMap.get(orderLogistics.getLogisticsNo()));
                }
                List<Integer> l1 = ll1.stream().map(LogisticsGoods::getGoodsId)
                        .collect(Collectors.toList());
                List<LogisticsGoods> l2 = new ArrayList<>();
                if (goodsMap.containsKey(pp.getLogisticsNo())) {
                    l2 = new ArrayList<>(goodsMap.get(pp.getLogisticsNo()));
                }
                if (orderLogistics.getReceiverInfo().equals(pp.getReceiverInfo())
                        && orderLogistics.getGoodsLabel().equals(pp.getGoodsLabel())
                        && orderLogistics.getWarehouse().equals(pp.getWarehouse())) {
                    for (LogisticsGoods g : l2) {
                        if (!l1.contains(g.getGoodsId())) {
                            goodsMap.get(pp.getLogisticsNo()).remove(g);
                            g.setLogisticsNo(orderLogistics.getLogisticsNo());
                            goodsMap.get(orderLogistics.getLogisticsNo()).add(g);
                            updateLogisticsGoodsNoList.add(g);
                            updateSpiltMergeStatusList.add(g.getLogisticsNo());
                        } else if (l1.contains(g.getGoodsId())) {
                            for (LogisticsGoods logisticsGoods : ll1) {
                                if (logisticsGoods.getGoodsId().equals(g.getGoodsId())) {
                                    if ((g.getIsRule().equals(IsRuleEnum.NO_RULE.getCode()) && logisticsGoods.getOrderNo().equals(g.getOrderNo())) ||
                                            (g.getIsRule().equals(IsRuleEnum.YES_RULE.getCode()) && logisticsGoods.getOrderNo().equals(g.getOrderNo()) &&
                                                    g.getGoodsAmount() + logisticsGoods.getGoodsAmount() <= g.getGoodsMaxAmount())) {
                                        goodsMap.get(pp.getLogisticsNo()).remove(g);
                                        goodsMap.get(orderLogistics.getLogisticsNo()).remove(logisticsGoods);
                                        logisticsGoods.setGoodsAmount(g.getGoodsAmount() + logisticsGoods.getGoodsAmount());
                                        goodsMap.get(orderLogistics.getLogisticsNo()).add(logisticsGoods);
                                        updateLogisticsGoodsAmountList.add(logisticsGoods);
                                        updateLogisticsGoodsDelList.add(g.getId());
                                        updateSpiltMergeStatusList.add(g.getLogisticsNo());
                                    } else if ((g.getIsRule().equals(IsRuleEnum.NO_RULE.getCode()) && !logisticsGoods.getOrderNo().equals(g.getOrderNo())) ||
                                            (g.getIsRule().equals(IsRuleEnum.YES_RULE.getCode()) && !logisticsGoods.getOrderNo().equals(g.getOrderNo()) &&
                                                    g.getGoodsAmount() + logisticsGoods.getGoodsAmount() <= g.getGoodsMaxAmount())) {
                                        goodsMap.get(pp.getLogisticsNo()).remove(g);
                                        g.setLogisticsNo(orderLogistics.getLogisticsNo());
                                        goodsMap.get(orderLogistics.getLogisticsNo()).add(g);
                                        updateLogisticsGoodsNoList.add(g);
                                        updateSpiltMergeStatusList.add(g.getLogisticsNo());
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        List<String> delOrderLogisticsList = goodsMap.entrySet().stream()
                .filter(k -> k.getValue().isEmpty()).map(k -> k.getKey()).collect(Collectors.toList());
        if (!delOrderLogisticsList.isEmpty()) {
            orderLogisticsMapper.batchUpdateDel(delOrderLogisticsList);
        }
        if (!updateSpiltMergeStatusList.isEmpty()) {
            orderLogisticsMapper.batchUpdateSpiltMergeStatusByLogisticsNo(updateSpiltMergeStatusList);
        }
        if (!updateLogisticsGoodsNoList.isEmpty()) {
            logisticsGoodsMapper.batchUpdateLogisticsNo(updateLogisticsGoodsNoList);
        }
        if (!updateLogisticsGoodsAmountList.isEmpty()) {
            logisticsGoodsMapper.batchUpdateGoodsAmount(updateLogisticsGoodsAmountList);
        }
        if (!updateLogisticsGoodsDelList.isEmpty()) {
            logisticsGoodsMapper.batchUpdateDelById(updateLogisticsGoodsDelList);
        }
        return true;
    }

    /**
     * 寻找该包裹下的商品
     *
     * @param paramList
     * @return
     */
    public Map<String, List<LogisticsGoods>> getLogisticsGoods(List<OrderLogistics> paramList) {
        Map<String, List<LogisticsGoods>> map = new HashMap<>();
        if (paramList.isEmpty()) {
            return map;
        }
        QueryWrapper<LogisticsGoods> queryWrapperGoods = new QueryWrapper<>();
        queryWrapperGoods.eq("del_flag", 0).eq("is_wdt_push", 0)
                .eq("logistics_status", LogisticsStatusEnum.WAIT_SEND.getCode()).eq("logistics_step", 1)
                .in("logistics_no", paramList.stream()
                        .map(OrderLogistics::getLogisticsNo).collect(Collectors.toList()));
        List<LogisticsGoods> logisticsGoodsList = logisticsGoodsMapper.selectList(queryWrapperGoods);
        for (LogisticsGoods g : logisticsGoodsList) {
            if (map.containsKey(g.getLogisticsNo())) {
                map.get(g.getLogisticsNo()).add(g);
                continue;
            }
            List<LogisticsGoods> list = new ArrayList<>();
            list.add(g);
            map.put(g.getLogisticsNo(), list);
        }
        return map;
    }

    /**
     * 生成包裹号
     *
     * @return
     */
    public String getLogisticsNo() {
        return autoSpiltService.getRandomString();
    }


    /**
     * 导出
     */
    public ExportExcelCommonResponse<ExcelSpiltMerge> excelExport(MergeListRequest request) {
        String goodsName = request.getGoodsName();
        String orderNoList = request.getOrderNoList();
        List<LogisticsGoods> list = logisticsGoodsMapper.exportLogisticsGoods(goodsName, orderNoList, request.getBenchmarkTime());
        Map<Integer, JmWarehouseResponse> warehouseMap = relocateService.getWarehouseInfo();
        Map<Integer, String> map = spiltMergeCategoryList();
        List<ExcelSpiltMerge> result = new ArrayList<>();
        String logisticsNo = "";
        for (LogisticsGoods logisticsGoods : list) {
            if (!logisticsNo.equals(logisticsGoods.getLogisticsNo())) {
                logisticsNo = logisticsGoods.getLogisticsNo();
                ExcelSpiltMerge excelSpiltMerge = new ExcelSpiltMerge();
                excelSpiltMerge.setA(logisticsGoods.getLogisticsNo());
                excelSpiltMerge.setK("否");
//                excelSpiltMerge.setL("否");
                if (logisticsGoods.getIsAlone().equals(IsAloneEnum.YES.getCode())) {
                    excelSpiltMerge.setB("单独发货包裹");
                    excelSpiltMerge.setK("是");
                }
//                else if (logisticsGoods.getIsGroup().equals(IsGroupEnum.YES.getCode())) {
//                    excelSpiltMerge.setC("组合商品包裹");
//                    excelSpiltMerge.setL("是");
//                }
                if (warehouseMap.containsKey(logisticsGoods.getRealWarehouse())) {
                    excelSpiltMerge.setE(warehouseMap.get(logisticsGoods.getRealWarehouse()).getWarehouseName());
                }
                excelSpiltMerge.setG(map.getOrDefault(logisticsGoods.getGoodsLabel(), ""));
                excelSpiltMerge.setM(logisticsGoods.getReceiverName());
                excelSpiltMerge.setN(logisticsGoods.getReceiverPhone());
                excelSpiltMerge.setO(logisticsGoods.getReceiverAddress());
                result.add(excelSpiltMerge);
            }
            ExcelSpiltMerge excelSpiltMerge = new ExcelSpiltMerge();
            excelSpiltMerge.setB(logisticsGoods.getGoodsId().toString());
            excelSpiltMerge.setC(logisticsGoods.getGoodsName());
            excelSpiltMerge.setD(logisticsGoods.getOrderNo());
            if (warehouseMap.containsKey(logisticsGoods.getRealWarehouse())) {
                excelSpiltMerge.setE(warehouseMap.get(logisticsGoods.getRealWarehouse()).getWarehouseName());
            }
            excelSpiltMerge.setF(logisticsGoods.getGoodsAmount().toString());
            excelSpiltMerge.setG(map.getOrDefault(logisticsGoods.getGoodsLabel(), ""));
            String totalWeight = new BigDecimal(logisticsGoods.getGoodsAmount()).multiply(logisticsGoods.getGoodsWeight()) + "kg";
            excelSpiltMerge.setH(totalWeight);
            excelSpiltMerge.setI(logisticsGoods.getIsRule().equals(IsRuleEnum.YES_RULE.getCode()) ? "有" : "无");
            excelSpiltMerge.setJ(logisticsGoods.getGoodsMaxAmount() != null ? logisticsGoods.getGoodsMaxAmount().toString() : "");
            excelSpiltMerge.setK(logisticsGoods.getIsAlone().equals(IsAloneEnum.YES.getCode()) ? "是" : "否");
//            excelSpiltMerge.setL(logisticsGoods.getIsGroup().equals(IsGroupEnum.YES.getCode()) ? "是" : "否");
            excelSpiltMerge.setM(logisticsGoods.getReceiverName());
            excelSpiltMerge.setN(logisticsGoods.getReceiverPhone());
            excelSpiltMerge.setO(logisticsGoods.getReceiverAddress());
            excelSpiltMerge.setP("否");
            excelSpiltMerge.setQ(logisticsGoods.getId().toString());
            result.add(excelSpiltMerge);
        }
        ExportExcelCommonResponse<ExcelSpiltMerge> response = new ExportExcelCommonResponse<>();
        response.setData(result);
        response.setFileName("ExcelSpiltMerge.xlsx");
        return response;
    }

    /**
     * 拆合单分类列表
     *
     * @return
     */
    public Map<Integer, String> spiltMergeCategoryList() {
        List list = iSpiltMergeCategoryService.findAll().getData();
        Map<Integer, String> map = new HashMap<>(list.size());
        for (Object object : list) {
            JmCategoryResponse jmCategoryResponse = JSON.parseObject(JSON.toJSONString(object), JmCategoryResponse.class);
            map.put(jmCategoryResponse.getCategoryId().intValue(), jmCategoryResponse.getCategoryName());
        }
        return map;
    }

    /**
     * 手动拆合单导入
     */
    public List<ExcelSpiltMerge> excelImport(HttpServletRequest request, MergeListRequest mergeListRequest) throws IOException {
        // 这里 需要指定读用哪个class去读，然后读取第一个sheet 文件流会自动关闭
        try {
            EasyExcel.read(request.getInputStream(), ExcelSpiltMerge.class, new SpiltMergeListener(mergeService, mergeListRequest)).sheet().doRead();
        } catch (ExcelAnalysisException | ExcelCommonException e) {
            throw new BaseException(500,"文件异常，请检查确认");
        }
        return errorList;
    }

    /**
     * 手动拆合单导入处理逻辑
     *
     * @param excelSpiltMergeList
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean excelImportHandler(List<ExcelSpiltMerge> excelSpiltMergeList, MergeListRequest request) {
        errorList.clear();
        String logisticsNo = "";
        String receiverPhone = "";
        String receiverAddress = "";
        String receiverName = "";
        String goodsLabel = "";
        String warehouseName = "";
        Integer maxAmount;
        String isAlone = null;
//        String isGroup = null;
        List<ExcelSpiltMerge> goods = null;
        int index = 0;
        List<String> delLogisticsList = new ArrayList<>();
        List<OrderLogistics> insertLogisticsList = new ArrayList<>();
        List<LogisticsGoods> updateLogisticsGoodsList = new ArrayList<>();
        List<LogisticsGoods> insertLogisticsGoodsList = new ArrayList<>();
        List<Integer> delLogisticsGoodsList = new ArrayList<>();
        Map<String, Integer> warehouseMap = getWarehouseInfo();
        Map<String, Integer> goodsLabelMap = getGoodsLabelInfo();
        int size = excelSpiltMergeList.size();
        boolean b = false;
        for (int i = 0; i < size; i++) {
            boolean haveGoods = false;
            ExcelSpiltMerge excelSpiltMerge = excelSpiltMergeList.get(i);
            if (excelSpiltMerge.getA() != null && !excelSpiltMerge.getA().trim().isEmpty() && !logisticsNo.equals(excelSpiltMerge.getA())) {
                if (b || (i == size - 1 && !excelSpiltMerge.getA().isEmpty())) {
                    if (b) {
                        delLogisticsList.add(logisticsNo);
                    } else if (i == size - 1 && !excelSpiltMerge.getA().isEmpty()) {
                        delLogisticsList.add(excelSpiltMerge.getA());
                    }
                    continue;
                }
                logisticsNo = excelSpiltMerge.getA();
                if (logisticsNo.length() == 30) {
                    goodsLabel = excelSpiltMerge.getG();
                    warehouseName = excelSpiltMerge.getE();
                    receiverName = excelSpiltMerge.getM();
                    receiverPhone = excelSpiltMerge.getN();
                    receiverAddress = excelSpiltMerge.getO();
                    isAlone = excelSpiltMerge.getB();
//                    isGroup = excelSpiltMerge.getC();
                }
                index = 0;
                goods = new ArrayList<>();
                b = true;
                continue;
            }
            ExcelSpiltMerge nextExcelSpiltMerge;
            if (i < size - 1) {
                nextExcelSpiltMerge = excelSpiltMergeList.get(i + 1);
                if (nextExcelSpiltMerge.getA() == null) {
                    haveGoods = true;
                }
            }
            if (index == 0) {
                b = false;
                if (logisticsNo.length() < 30) {
                    goodsLabel = excelSpiltMerge.getG();
                    warehouseName = excelSpiltMerge.getE();
                    receiverName = excelSpiltMerge.getM();
                    receiverPhone = excelSpiltMerge.getN();
                    receiverAddress = excelSpiltMerge.getO();
                    isAlone = excelSpiltMerge.getK();
//                    isGroup = excelSpiltMerge.getL();
                }
            }
            index++;
            if (logisticsNo.length() == 30 || (logisticsNo.length() < 30 && index > 1)) {
                if (isAlone != null && excelSpiltMerge.getK().equals("否")) {
                    ExcelSpiltMerge errorExcelSpiltMerge = new ExcelSpiltMerge();
                    BeanUtils.copyProperties(excelSpiltMerge, errorExcelSpiltMerge);
                    errorExcelSpiltMerge.setA(logisticsNo);
                    errorExcelSpiltMerge.setR("违反单独发货规则");
                    errorList.add(errorExcelSpiltMerge);
                    continue;
                }
//                if (isGroup != null && excelSpiltMerge.getL().equals("否")) {
//                    ExcelSpiltMerge errorExcelSpiltMerge = new ExcelSpiltMerge();
//                    BeanUtils.copyProperties(excelSpiltMerge, errorExcelSpiltMerge);
//                    errorExcelSpiltMerge.setA(logisticsNo);
//                    errorExcelSpiltMerge.setR("违反组合商品规则");
//                    errorList.add(errorExcelSpiltMerge);
//                    continue;
//                }
            }
            if (index > 1 && (!excelSpiltMerge.getN().equals(receiverPhone) || !excelSpiltMerge.getO().equals(receiverAddress) || !excelSpiltMerge.getG().equals(goodsLabel)
                    || !excelSpiltMerge.getE().equals(warehouseName))) {
                ExcelSpiltMerge errorExcelSpiltMerge = new ExcelSpiltMerge();
                BeanUtils.copyProperties(excelSpiltMerge, errorExcelSpiltMerge);
                errorExcelSpiltMerge.setA(logisticsNo);
                if (!excelSpiltMerge.getN().equals(receiverPhone) || !excelSpiltMerge.getO().equals(receiverAddress)) {
                    errorExcelSpiltMerge.setR("收件人信息不一致");
                } else if (!excelSpiltMerge.getG().equals(goodsLabel)) {
                    errorExcelSpiltMerge.setR("拆合单分类不一致");
                } else if (!excelSpiltMerge.getE().equals(warehouseName)) {
                    errorExcelSpiltMerge.setR("发货仓不一致");
                }
                errorList.add(errorExcelSpiltMerge);
                continue;
            }
            if (index > 1 && excelSpiltMerge.getI().equals("有")) {
                maxAmount = Integer.parseInt(excelSpiltMerge.getJ());
                List<ExcelSpiltMerge> list = goods.stream().filter(e -> e.getB().equals(excelSpiltMerge.getB()))
                        .collect(Collectors.toList());
                Integer max = 0;
                if (!list.isEmpty()) {
                    for (ExcelSpiltMerge e : list) {
                        max = max + Integer.parseInt(e.getF());
                    }
                    max = max + Integer.parseInt(excelSpiltMerge.getF());
                    if (max > maxAmount) {
                        ExcelSpiltMerge errorExcelSpiltMerge = new ExcelSpiltMerge();
                        BeanUtils.copyProperties(excelSpiltMerge, errorExcelSpiltMerge);
                        errorExcelSpiltMerge.setA(logisticsNo);
                        errorExcelSpiltMerge.setR("超过最大数量限制");
                        errorList.add(errorExcelSpiltMerge);
                        continue;
                    }
                }
            }
            goods.add(excelSpiltMerge);
            //符合条件的包裹逻辑
            if (!haveGoods && logisticsNo.length() < 30 && !errorList.isEmpty()) {
                //新建包裹
                logisticsNo = autoSpiltService.getRandomString();
                OrderLogistics orderLogistics = new OrderLogistics();
                orderLogistics.setLogisticsNo(logisticsNo);
                orderLogistics.setSpiltMergeStatus(SpiltMergeStatusEnum.SPILT.getCode());
                orderLogistics.setWarehouse(warehouseMap.get(warehouseName));
                orderLogistics.setGoodsLabel(goodsLabelMap.get(goodsLabel));
                orderLogistics.setReceiverAddress(receiverAddress);
                orderLogistics.setReceiverName(receiverName);
                orderLogistics.setReceiverPhone(receiverPhone);
                orderLogistics.setReceiverInfo(receiverPhone + receiverAddress);
                orderLogistics.setSelfFlag(SelfFlagEnum.YES_SELF.getCode());
                orderLogistics.setIsAlone(excelSpiltMerge.getK().equals("是") ? (byte) 1 : 0);
                orderLogistics.setLogisticsStatus(LogisticsStatusEnum.WAIT_SEND.getCode());
//                orderLogistics.setIsGroup(excelSpiltMerge.getL().equals("是") ? (byte) 1 : 0);
                orderLogistics.setCreateTime(request.getBenchmarkTime());
                insertLogisticsList.add(orderLogistics);
            }
            if (!haveGoods && !errorList.isEmpty()) {
//                goods = mergeGoods(goods);
                //修改包裹号
                for (ExcelSpiltMerge g : goods) {
                    LogisticsGoods logisticsGoods = new LogisticsGoods();
                    if (g.getP().equals("是")) {
                        //插入 获取原商品信息
                        LogisticsGoods lg = getGoodsById(Integer.parseInt(g.getQ()));
                        BeanUtils.copyProperties(lg, logisticsGoods);
                        logisticsGoods.setId(null);
                        logisticsGoods.setLogisticsNo(logisticsNo);
                        logisticsGoods.setGoodsAmount(Integer.parseInt(g.getF()));
                        insertLogisticsGoodsList.add(logisticsGoods);
                        delLogisticsGoodsList.add(lg.getId());
                    } else {
                        logisticsGoods.setId(Integer.parseInt(g.getQ()));
                        logisticsGoods.setLogisticsNo(logisticsNo);
                        logisticsGoods.setGoodsAmount(Integer.parseInt(g.getF()));
                        updateLogisticsGoodsList.add(logisticsGoods);
                    }
                }
            }
        }
        if (errorList.isEmpty()) {
            if (!delLogisticsList.isEmpty()) {
                orderLogisticsMapper.batchUpdateDel(delLogisticsList);
            }
            if (!delLogisticsList.isEmpty()) {
                logisticsGoodsMapper.batchUpdateDel(delLogisticsList);
            }
            if (!insertLogisticsList.isEmpty()) {
                orderLogisticsMapper.batchInsertLogistics(insertLogisticsList);
            }
            if (!insertLogisticsGoodsList.isEmpty()) {
                logisticsGoodsMapper.batchInsertGoods(insertLogisticsGoodsList);
            }
            if (!updateLogisticsGoodsList.isEmpty()) {
                logisticsGoodsMapper.batchUpdateLogisticsNoById(updateLogisticsGoodsList);
            }
            if (!delLogisticsGoodsList.isEmpty()) {
                logisticsGoodsMapper.batchUpdateDelById(delLogisticsGoodsList);
            }
        }
        return true;
    }


    /**
     * 将包裹中相同的物品合并数量
     *
     * @param list
     * @return
     */
    public List<ExcelSpiltMerge> mergeGoods(List<ExcelSpiltMerge> list) {
        List<ExcelSpiltMerge> newList = new ArrayList<>();
        for (ExcelSpiltMerge oldO : list) {
            boolean flag = true;
            for (ExcelSpiltMerge newO : newList) {
                if (oldO.equals(newO)) {
                    newO.setF(String.valueOf(Integer.parseInt(newO.getF()) + Integer.parseInt(oldO.getF())));
                    flag = false;
                }
            }
            if (flag) {
                newList.add(oldO);
            }
        }
        return newList;
    }

    public LogisticsGoods getGoodsById(Integer id) {
        QueryWrapper<LogisticsGoods> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("del_flag ", 0).eq("id", id);
        return logisticsGoodsMapper.selectOne(queryWrapper);
    }


    public Map<String, Integer> getGoodsLabelInfo() {
        List list = iSpiltMergeCategoryService.findAll().getData();
        Map<String, Integer> map = new HashMap<>(list.size());
        for (Object object : list) {
            JmCategoryResponse jmCategoryResponse = JSON.parseObject(JSON.toJSONString(object), JmCategoryResponse.class);
            map.put(jmCategoryResponse.getCategoryName(), jmCategoryResponse.getCategoryId().intValue());
        }
        return map;
    }

    /**
     * 获取全部仓库信息
     *
     * @return
     */
    public Map<String, Integer> getWarehouseInfo() {
        List<JmWarehouseResponse> list = iWarehouseService.findAll().getData();
        Map<String, Integer> map = new HashMap<>(list.size());
        for (JmWarehouseResponse jmWarehouseResponse : list) {
            map.put(jmWarehouseResponse.getWarehouseName(), jmWarehouseResponse.getWarehouseId().intValue());
        }
        return map;
    }


//    public Byte hhhh(){
//        UpdateWrapper<UserOrder> updateWrapper = new UpdateWrapper<>();
//        updateWrapper.eq("order_no","2012141354143696586").eq("order_status",0);
//        return userOrderMapper.selectOne(updateWrapper).getOrderStatus();
//    }
//
//    @Resource
//    UserOrderMapper userOrderMapper;
//    @Transactional(rollbackFor = Exception.class)
//    public void test(){
//        UpdateWrapper<UserOrder> updateWrapper = new UpdateWrapper<>();
//        updateWrapper.eq("order_no","2012141354143696586");
//        UserOrder userOrder = new UserOrder();
//        userOrder.setOrderStatus((byte)0);
//        userOrderMapper.update(userOrder,updateWrapper);
//        Byte b = hhhh();
//        updateWrapper = new UpdateWrapper<>();
//        updateWrapper.eq("order_no","2012141354143696586");
//        userOrder = new UserOrder();
//        userOrder.setOrderStatus((byte)-1);
//        userOrderMapper.update(userOrder,updateWrapper);
//    }

}
